昨天說到了之前從未特別談過的kong
授權的問題,因為如果僅有做認證,那就沒有辦法一次將多個API
服務納管到kong
上進行一致的管理了。這顯然不符合一個合格的API Gateway
的產品。
在前面Day 6的時候有介紹到,kong
的協助轉換的核心是建立在service
、route
以及service
上,大多數其他附加的功能都是建立在plugin
之上。認證授權其實也是一樣,就例如之前所有認證的範例,都是使用apikey
的方式來進行consumer
身份辨識,而授權則是使用ACL
這個plugin
來進行。就讓我們一起進入Sam與Aries的討論,共同理解這個套件的使用方式。
圖19-1 ACL
Aries: Sam,我大概理解怎樣使用了,其實滿直觀的,當然也是有一些雷坑需要注意,還有要如何規劃也是需要思考的。
Sam: 你說說看研究到的內容,我很期待。
Aries: 我是模仿之前的設定,將需要apikey
的認證的route
後面,直接設定了ACL
plugin。而且同樣的在consumer
的位置,新增了ACL
的設定。不過這裡就是我說雷的地方,因為原廠文件其實沒有把這件事情的declaretive yaml
寫得非常詳細,所以我試錯了滿多次的。
Sam: 很不錯,踩過的雷都是自己的,那你最後是怎麼試出來的?
Aries: 我去翻找了內部曾經建立過workspace
,接著把Kong Control Plane Setting使用deck
匯出後,才發現箇中奧秘的。
Sam: 這真的是一個好方法,那就一起來看看設定要如何進行吧~
這次為了示範,前一天有說明建立了兩個route
,今天就基於昨天的kong.yml
來繼續說明,要如何在route
上面將acl
plugin建立起來。
請參考
ironman2025\case_ELK_JPG_AuthZN\1.Kong_declarative\declarative\kong.yml
services:
- name: case_ELK_JPG_AuthZN
url: http://case_ELK_JPG_AuthZN:8080
routes:
- name: case_ELK_JPG_AuthZN
paths:
- /case_ELK_JPG_AuthZN/
plugins:
...中間省略...
- name: acl
config:
allow:
- VIP
- trial
deny: null
hide_groups_header: false
enabled: true
protocols:
- grpc
- grpcs
- http
- https
tags:
- VIP
- trial
- name: case_ELK_JPG_AuthZN_weather
url: http://case_ELK_JPG_AuthZN_weather:8080
routes:
- name: case_ELK_JPG_AuthZN_weather
paths:
- /case_ELK_JPG_AuthZN_weather/
plugins:
...中間省略...
- name: acl
config:
allow:
- VIP
deny: null
hide_groups_header: false
enabled: true
protocols:
- grpc
- grpcs
- http
- https
tags:
- VIP
可以注意到在case_ELK_JPG_AuthZN
與case_ELK_JPG_AuthZN_weather
這兩個route
,都設定了一組 ACL
plugin。其實就是各自在不同的route
上面,建立了可以被許可授權存取的群組名稱,整理如下:
route
: case_ELK_JPG_AuthZN
acl
: vipacl
: trailroute
: case_ELK_JPG_AuthZN_weather
acl
: vip當設定好route
上面可授權存取的群組後,接著當然是要在consumer
的部分,將權限授予不同的來源,當然還是回到kong.yml
來說明這件事情。
consumers:
- acls:
- group: VIP
username: user1@user.com
custom_id: user1
keyauth_credentials:
- key: user1-api-key
- acls:
- group: trial
username: user2@user.com
custom_id: user2
keyauth_credentials:
- key: user2-api-key
可以注意到如果不同的user
被授予了不同的group
,同樣列點如下:
username
: user1@user.com
group
: VIPusername
: user1@user.com
group
: trial這邊最雷的就是,原本在yaml僅定義
consumer
的時候,該元素是對齊yaml的最左邊無空格(第0列)。但是當加上acl
的時候,居然是acl
這個元素對齊最左邊。
筆者在茫茫網海中找了許久,真的沒有找到範本,大多數的範例都是使用UI進行設定的。最後筆者也是透過UI先設定進去,再用deck
dump出來比對,才找到答案。
而更討厭的是,kong
的原廠文件關於這一段的說明,則是:_format_version: "1.1" ... consumers: - username: api-second-user acls: - group: guest - username: api-user acls: - group: developer
但這段....試了半天根本就沒有作用,筆者猜測這是給
deck
讀取並同步用的,但轉譯成declaretive yaml根本不是這回事。
有興趣的讀者請回饋,告訴筆者是哪一步做錯了,讓筆者耗費了一個晚上找答案。參考網址 :How to define ACLs in a declarative config for decK補充:deck 是kong為了declaretive mode所出的開源專案,這個小工具其實用途也多多,後面會介紹到。
圖19-2 ACL 圖示說明
請讀者參考圖19-2,可以看到group:VIP
有權限存取兩個API
,但如果只是group:trial
則僅能存取 case_ELK_JPG_AuthZN
。
可以看到,這種授權策略是將consumer
進行分群(類似分等級),並將不同的API
授權給不同群體,這種授權策略在API
端會有較多種group
被貼上。
既然已經授權完成,那當然就要驗證看看。筆者這裡就不一一貼上每一個請求畫面,而是使用Kibana
作為查找請求的紀錄。筆者分別用user1@user.com
與user2@user.com
對兩個API
進行了各一次的請求,得到的紀錄如圖19-3:
圖 19-3 Kibana的請求紀錄
可以注意到,user2@user.com
這位使用者雖然認證正確(如果認證失敗會是401),但在case_ELK_JPG_AuthZN_weather
這個API
並未被正確的授權,因此最終得到了一個403(Forbidden)。如果讀者是使用postman
進行實驗,則還會在response的body得到更進階的message。
圖19-4 postman 中更進階的未授權資訊
Sam: 不錯,你的確將kong
的認證授權大致上說明的很清楚了。
Aries: 其實滿直觀的,不過要如何正確的分類或是給予不同的權限,好像也是可以弄得非常的複雜,這在管理上好像也是值得探討的議題。
Sam: 的確是,另外要是kong
的declaretive yaml 要是有更多資訊可以從網路上查到就好了,這對我們這些喜歡透過自動化管道進行IaC管理的研究者會是更大的福音。
Aries: 居然還要再裝一個kong
設定完後,再用另外一個deck
匯出才可以知道正確答案還真是....
Sam: 好啦,免錢的社群版,很棒棒惹(笑)。
補充:這邊說到的是以
consumer
分角色來授權,另外一種常見的策略,則是在route
中直接貼上例如routename
後,一一授權給所有的consumer
,可以參考圖19-5。
圖 19-5 不同的管理策略這也是常見的管理方式,相較於需要將
consumer
分群的方式來看,其實也非常的直觀。不過這部分有一個需要注意的地方,請筆者看到 圖19-6。
圖 19-6 往上游附加的資訊這一個欄位叫做
request.header.x-consumer-groups
的欄位,這欄位是在認證授權通過的時,kong
會將相關請求的認證授權資訊,向上游發送並附加在header
中。筆者就遇過由於設定者過度分權,將每一個
API
都設定為一個route
(每一支喔!不是以一個站為單位喔!),然後將不同的API
進行一一的貼標。這導致大量的groups
被授權到consumer
身上,當認證授權通過後,就會有極大量的request.header.x-consumer-groups
被附加在請求header
中。最終header超出了服務器許可的上限大小(IIS 好像是16KB,不同服務器有不同大小),回應了400的錯誤,最終查了半天才知道原因。
筆者其實認為這是一種很直觀的分權管理設定方式,但所有的分權還是要有所限制,過於分權不只造成了管理上設定的繁瑣,更是在未來哪一天可能會埋下不知為何的異常錯誤。
P.S
kong
其實可以關閉往後送這個資訊,可以參考到kong.yam 中acl
plugin 的hide_groups_header
這個參數,如果讀者未來遇到了希望可以短解,這也是一種作法,但最終還是要注意過度分權可能造成的一些極限異常問題。